var view = {}

function paintCube (cube) {

  let uf = cube.getFace('up')
  let df = cube.getFace('down')
  let lf = cube.getFace('left')
  let rf = cube.getFace('right')
  let ff = cube.getFace('front')
  let bf = cube.getFace('behind')

  paintFace(view.ubs, uf)
  paintFace(view.dbs, df)
  paintFace(view.fbs, ff)
  paintFace(view.bbs, bf)
  paintFace(view.rbs, rf)
  paintFace(view.lbs, lf)

  function paintFace (face, colors) {
    for (let i = 0; i < colors.length; i++) {
      face[i].firstChild.style.backgroundColor = ColorValue[colors[i]]
    }
  }

  paintLook(cube)
}

/**
 * 旋转
 * @param cube
 * @param op 方向控制字符
 */
function rotateLayer3d (cube, op) {

  let interval = config.view.rotateInterval

  let op_c = op
  let isClockwise = !(/`/.test(op))
  op = op.replace('`', '')
  let center = config.cube.size / 2
  let deg = 0
  let roFace = view.faces[op]

  //定时器
  let timer = setInterval(function () {
    isClockwise ? deg++ : deg--

    roFace.forEach(function (item) {
      let ox = Math.floor(center - item.offsetLeft)
      let oy = Math.floor(center - item.offsetTop)
      let oz = 0
      rotateZAround(item, deg, ox, oy, oz)
    })

    let oz = -center

    switch (op) {
      case 'U':
        view.sides['U'].forEach(function (side) {
          let ox = Math.floor(center - side.offsetLeft)
          rotateYAround(side, -deg, ox, oz)
        })
        break
      case 'D':
        view.sides['D'].forEach(function (side) {
          let ox = Math.floor(center - side.offsetLeft)
          rotateYAround(side, deg, ox, oz)
        })
        break
      case 'F': {
        view.side['UF'].forEach(function (side) {
          let ox = Math.floor(center - side.offsetLeft)
          rotateYAround(side, deg, ox, oz)
        })
        view.side['DF'].forEach(function (side) {
          let ox = Math.floor(center - side.offsetLeft)
          rotateYAround(side, -deg, ox, oz)
        })
        view.side['LF'].forEach(function (side) {
          let oy = Math.floor(center - side.offsetTop)
          rotateXAround(side, deg, oy, oz)
        })
        view.side['RF'].forEach(function (side) {
          let oy = Math.floor(center - side.offsetTop)
          rotateXAround(side, -deg, oy, oz)
        })
      }
        break
      case 'B': {
        view.side['UB'].forEach(function (side) {
          let ox = Math.floor(center - side.offsetLeft)
          rotateYAround(side, -deg, ox, oz)
        })
        view.side['DB'].forEach(function (side) {
          let ox = Math.floor(center - side.offsetLeft)
          rotateYAround(side, deg, ox, oz)
        })
        view.side['LB'].forEach(function (side) {
          let oy = Math.floor(center - side.offsetTop)
          rotateXAround(side, -deg, oy, oz)
        })
        view.side['RB'].forEach(function (side) {
          let oy = Math.floor(center - side.offsetTop)
          rotateXAround(side, deg, oy, oz)
        })
      }
        break
      case 'L': {
        rotateLs1(view.side['UL'])
        rotateLs1(view.side['FL'])
        rotateLs1(view.side['DL'])

        function rotateLs1 (ls1) {
          ls1.forEach(function (side) {
            let oy = Math.floor(center - side.offsetTop)
            rotateXAround(side, -deg, oy, oz)
          })
        }

        view.side['BL'].forEach(function (side) {
          let oy = Math.floor(center - side.offsetTop)
          rotateXAround(side, deg, oy, oz)
        })
        break
      }
      case 'R': {
        rotateRs1(view.side['UR'])
        rotateRs1(view.side['FR'])
        rotateRs1(view.side['DR'])

        function rotateRs1 (rs1) {
          rs1.forEach(function (side) {
            let oy = Math.floor(center - side.offsetTop)
            rotateXAround(side, deg, oy, oz)
          })
        }

        view.side['BR'].forEach(function (side) {
          let oy = Math.floor(center - side.offsetTop)
          rotateXAround(side, -deg, oy, oz)
        })
        break
      }
    }

    if (deg >= 90 || deg <= -90) {
      clearInterval(timer)
      roFace.forEach(function (item) {
        clearTransform(item)
      })
      for (let sidesKey in view.sides) {
        view.sides[sidesKey].forEach(function (item) {
          clearTransform(item)
        })
      }
      cube.rotate(op_c)
      paintCube(cube)
    }
  }, interval)
}

function rotateCube3d (cube, op) {
  var c1 = new Date().getMilliseconds()
  let clockWise = /`/.test(op)
  let op_c = op.replace('`', '')
  let deg = 0
  var timer = setInterval(function () {
    clockWise ? deg++ : deg--
    switch (op_c) {
      case 'x': {
        rotateXAround(view.allFace, -deg, config.cube.size / 2, 0)
        break
      }
      case 'y': {
        rotateYAround(view.allFace, deg, config.cube.size / 2, 0)
        break
      }
      case 'z': {
        rotateZAround(view.allFace, -deg, config.cube.size / 2, config.cube.size / 2)
        break
      }
    }
    if (deg >= 90 || deg <= -90) {
      clearInterval(timer)
      clearTransform(view.allFace)
      let step = clockWise ? 1 : 3
      switch (op_c) {
        case 'x':
          cube.rotateX(step)
          break
        case 'y':
          cube.rotateY(step)
          break
        case 'z':
          cube.rotateZ(step)
          break
      }
      paintCube(cube)
      var c2 = new Date().getMilliseconds()
      console.log(c2 - c1)
    }
  }, config.view.rotateInterval)
}

function rotate3d (cube, op) {
  if (/[xyz]/.test(op))
    rotateCube3d(cube, op)
  else
    rotateLayer3d(cube, op)
}

function rotatePattern3d (cube, pattern) {
  let steps = pattern.split(' ')
  let i = 0
  var timer = setInterval(function () {
    if (i < steps.length) {
      rotate3d(cube, steps[i])
      i++
    } else {
      clearInterval(timer)
    }
  }, config.view.stepInterval)
}

/**
 * 获取魔方每个方块的dom对象
 */
function initViewObj () {
  view.ubs = document.querySelectorAll('.u > .block')
  view.dbs = document.querySelectorAll('.d > .block')
  view.rbs = document.querySelectorAll('.r > .block')
  view.lbs = document.querySelectorAll('.l > .block')
  view.fbs = document.querySelectorAll('.f > .block')
  view.bbs = document.querySelectorAll('.b > .block')

  view.allFace = document.getElementsByClassName('face')[0]

  view.faces = {
    'U': view.ubs,
    'D': view.dbs,
    'L': view.lbs,
    'R': view.rbs,
    'F': view.fbs,
    'B': view.bbs,
  }

  view.side = {}
  view.sides = {}

  const opList = 'UDFBLR'
  for (let i = 0; i < 6; i++) {
    for (let j = 0; j < 6; j++) {
      let t = opList[i] + opList[j]
      if (opList[i] === opList[j] || /(UD|DU|LR|RL|FB|BF)/.test(t)) continue
      let query = '.' + opList[i].toLowerCase() + ' > .s' + opList[j].toLowerCase()
      view.side[opList[i] + opList[j]] = document.querySelectorAll(query)
    }
    view.sides[opList[i]] = document.querySelectorAll('.s' + opList[i].toLowerCase())
  }
}

function createPaper () {
  document.querySelectorAll('.block').forEach(function (item) {
    let paper = document.createElement('div')
    paper.className = 'paper'
    item.appendChild(paper)
  })
}

function paintLook (cube) {
  let can = document.getElementById('look')
  let ctx = can.getContext('2d')
  ctx.fillStyle = 'darkgray'
  ctx.fillRect(0, 0, 405, 400)

  let uf = cube.getFace('up')
  let df = cube.getFace('down')
  let lf = cube.getFace('left')
  let rf = cube.getFace('right')
  let ff = cube.getFace('front')
  let bf = cube.getFace('behind')

  let defaultWidth = 45
  let defaultInterval = 5
  let interval = defaultWidth + defaultInterval

  paintFace({ x: 105, y: 50 }, uf)
  paintFace({ x: 5, y: 150 }, lf)
  paintFace({ x: 105, y: 150 }, ff)
  paintFace({ x: 205, y: 150 }, rf)
  paintFace({ x: 305, y: 150 }, bf)
  paintFace({ x: 105, y: 250 }, df)

  function paintFace (pos, face) {
    let posList = [
      { x: pos.x, y: pos.y },
      { x: pos.x + interval, y: pos.y },
      { x: pos.x, y: pos.y + interval },
      { x: pos.x + interval, y: pos.y + interval }
    ]
    for (let i = 0; i < face.length; i++) {
      ctx.fillStyle = ColorValue[face[i]]
      ctx.fillRect(posList[i].x, posList[i].y, defaultWidth, defaultWidth)
    }
  }
}